Zum Hauptinhalt springen

Einheit 7 — Testen ohne Nebenwirkungen

Was du nach dieser Einheit weißt: Du kannst einzelne Agents mit einer Beispiel-Payload testen, bevor sie Teil eines laufenden Workflows werden — und du weißt, welche Agents sich im Testlauf tatsächlich zurückhalten und welche nicht.

Kurs 5, Einheit 4 hat den Grundsatz aufgestellt: Abschnitte isoliert testen, bevor das Ganze läuft. agent_test_run ist das Werkzeug dafür in Textform — nur feiner. Es testet einen Agent.

Zwei Betriebsarten

Bestehender Agent

{
"agent_id": 1902,
"input_payload": { "name": "Testperson", "company": "42grad GmbH" }
}

Der Agent wird mit seiner echten Konfiguration ausgeführt, aber ohne bleibende Nachrichten.

Virtueller Agent

Du kannst einen Agent testen, den es noch gar nicht gibt:

{
"agent_type": "Agents::PostAgent",
"name": "probe",
"options": {
"post_url": "https://api.example.com/contacts",
"method": "post",
"content_type": "json",
"no_merge": true,
"payload": { "name": "{{ name }}" }
},
"input_payload": { "name": "Testperson" }
}

Damit prüfst du eine Konfiguration, bevor du sie deployst. Sehr nützlich, um einen Request-Aufbau zu klären, ohne den Workflow anzufassen.

Aliasnamen funktionieren hier nicht

Bei virtuellen Agents akzeptiert agent_test_run keine Alias-Node-Typen. towelscript_type: "http.post" scheitert mit Unknown TowelScript node type: http.post.

Nutze für virtuelle Läufe entweder den Basisnamen (http) oder — eindeutiger — den Rails-Typ agent_type: "Agents::PostAgent".

Für bestehende Agents mit agent_id stellt sich die Frage nicht.

Die Payload muss stimmen — genau stimmen

Das ist die mit Abstand häufigste Fehlerquelle. input_payload wird zur message.payload, die der Agent bekommt. Sie muss exakt die Struktur haben, die der vorgelagerte Agent erzeugen würde.

Ein Beispiel: Der Webhook Agent legt den kompletten POST-Body ab. Kommt herein

{ "data": { "temperature": 23.5 } }

dann ist das die Payload — und nicht { "temperature": 23.5 }. Testest du mit der flachen Variante, läuft der Dry-Run durch und der echte Lauf scheitert, weil message.payload.data.temperature nicht existiert.

Payload nicht erfinden, sondern abschreiben

Der zuverlässigste Weg zu einer korrekten Testpayload ist eine echte:

  1. agent_messages auf den vorgelagerten Agent aufrufen
  2. Die payload aus einer echten Nachricht kopieren
  3. Als input_payload verwenden

Alternativ nimmst du eine bestehende Nachricht direkt: agent_test_run akzeptiert auch message_id.

Was im Dry-Run wirklich passiert

„Dry-Run" heißt nicht, dass nichts passiert. Es heißt, dass keine bleibenden Nachrichten erzeugt werden. Ob ein Agent nach außen wirkt, hängt vom Agent ab:

AgentIm Dry-Run
Post Agent — POST, PUTsendet nicht, protokolliert aber den vollständig gebauten Request
Post Agent — GETsendet wirklich
Shell Command Agentführt nicht aus
CSV Agentschreibt die Datei wirklich
Doc Converter Agentschreibt die Datei wirklich
Generative AI Agentruft das Modell wirklich auf (kostet Tokens)
Kein Freibrief

Ein GET-Request kann eine Aktion auslösen. Eine geschriebene Datei kann eine Ordnerüberwachung triggern. Behandle agent_test_run als „minimal-invasiv", nicht als „folgenlos" — und teste gegen ein Testsystem, wenn das Zielsystem echte Daten enthält.

Das Log ist der eigentliche Ertrag

Beim Post Agent steht im Dry-Run-Log der Request, wie er gesendet würde:

Preparing POST request to https://…/contacts
headers: {"Content-Type" => "application/json; charset=utf-8"}
Dry run: Would send POST request to https://…/contacts
Full request: {method: "POST", url: "https://…/contacts",
headers: {"Content-Type" => "application/json; charset=utf-8"},
body: "{\"name\":\"Testperson\",\"company\":\"42grad GmbH\"}"}

Das ist genau die Information, die du sonst nur über einen Request-Inspector bekommst — Ziel, Header, Body, alles nach dem Rendern der Liquid-Ausdrücke.

Ein Beispiel, das man im Log sofort sieht

Der Post Agent erwartet payload als Objekt. Schreibt man stattdessen einen JSON-String hinein, wird der Body doppelt kodiert:

body: "\"{\\\"name\\\": \\\"Testperson\\\"}\""

Der Body ist ein String, der JSON enthält — nicht JSON. Die Gegenstelle antwortet je nach Nachsicht mit 400 oder legt einen leeren Datensatz an. Im Log sieht man es in zwei Sekunden.

Zum Vergleich der korrekte Fall mit payload als Objekt:

body: "{\"name\":\"Testperson\",\"company\":\"42grad GmbH\"}"

📸 Screenshot: [Platzhalter — Zwei Dry-Run-Logs nebeneinander: doppelt kodierter Body vs. korrekter Body]

Mehrere Eingangsnachrichten

Agents, die mehrere Quellen zusammenführen (etwa json.merge), testest du mit input_messages statt input_payload — einem Array von Payload-Objekten.

Die Arbeitsschleife

1. workflow_show      → Agent-ID und erwartete Payload-Struktur klären
2. agent_messages → echte Payload des Vorgängers holen
3. agent_test_run → mit dieser Payload prüfen
4. agent_update → Konfiguration korrigieren
5. zurück zu 3

Erst wenn der Agent allein funktioniert, lässt du den ganzen Workflow laufen.

Zusammengefasst

RegelWarum
Payload abschreiben, nicht erfindenDer häufigste Grund für „Test grün, Produktion rot"
Virtuelle Agents mit agent_type ansprechenAliasnamen werden nicht aufgelöst
Log lesen, nicht nur successDer gebaute Request steht dort vollständig
Dry-Run ist nicht folgenlosGET sendet, CSV und Convert schreiben, KI kostet
Erst einzeln, dann im VerbundEin Fehler in einem Agent ist leichter zu finden als in zwölf

Weiter: Einheit 8 — Deployen und ausführen